package com.fantaike.array.sparsearray;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;

import java.io.*;

/**
 * @author jishushen
 * @create 2021-07-03 16:56
 * 稀疏数组
 */
public class SparseArray {

    public static void main(String[] args) {
//        arrayToSparse();
        try {
            excelToSparseArray();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 二维数组转稀疏数组的思路：
     * 1.遍历原始的二维数组，得到有效数据的个数 sum
     * 2.根据sum就可以 创建稀疏数组sparseArr int[sum+1][3]
     * 3.将二维数组的有效数据 存入到稀疏数组中
     */
     public static void arrayToSparse(){
         //创建一个原始的二维数组 11 * 11
         //以棋盘为例 0:表示没有棋子 1：表示黑子  2 表示白子
         int[][] chessArray = new int[11][11];
         chessArray[1][2] = 1;
         chessArray[2][3] = 2;
         chessArray[3][4] = 1;
         chessArray[4][5] = 2;
         //增强for第一次遍历出的是行
         System.err.println("原始的二维数组");
         for (int[] rows : chessArray) {
             //这次遍历的为数据
             for (int data : rows) {
                 System.out.printf("%d\t",data);
             }
             System.out.println();
         }

         //要获取除0以外的数据个数
         int sum = 0;
         //获取二维数组行的长度
         int rows = chessArray.length;
         //获取二维数组列的长度
         int columns = chessArray[0].length;
         for (int i = 0; i < rows; i++) {
             for (int j = 0; j < columns; j++) {
                 if (chessArray[i][j] != 0)
                     sum++;
             }
         }
         System.out.println("共有不同于0的数据 sum = " + sum + " 个");

         //创建稀疏数组
         int[][] sparseArray = new int[sum + 1][3];
         //给稀疏数组第一行赋值
         sparseArray[0][0] = rows;
         sparseArray[0][1] = columns;
         sparseArray[0][2] = sum;

         //给稀疏数组除0行外赋值
         int count = 0;
         for (int i = 0; i < rows; i++) {
             for (int j = 0; j < columns; j++) {
                 if (chessArray[i][j] != 0){
                     count++;
                     sparseArray[count][0] = i;
                     sparseArray[count][1] = j;
                     sparseArray[count][2] = chessArray[i][j];
                 }
             }
         }
         System.out.println("输出的稀疏数组为：");
         for (int[] row : sparseArray) {
             for (int data : row) {
                 System.out.printf("%d\t",data);
             }
             System.out.println();
         }

         //调用将稀疏数组转换成二维数组
         sparseToArray(sparseArray);

         //将稀疏数组存入到excel表中
         try {
             sparseToExcel(sparseArray);
         } catch (IOException e) {
             e.printStackTrace();
         }
     }

    /**
     * 稀疏数组 转 二维数组
     * 1.先读取稀疏数组的第一行，根据第一行的数据，创建原始的二维数组。
     * 2.再读取稀疏数组的后几行的数据并赋给 原始的二维数组即可
     */
    public static void sparseToArray(int[][] sparseArray){
        //创建原始二维数组
        int[][] chessArray = new int[sparseArray[0][0]][sparseArray[0][1]];
        //遍历稀疏数组，将稀疏数组的内容赋值到响应的原始数组;注意：应该从行为1开始遍历
        for (int i = 1; i < sparseArray.length; i++) {
            chessArray[sparseArray[i][0]][sparseArray[i][1]] = sparseArray[i][2];
        }
        System.out.println("还原的原始数组为：");
        for (int[] rows : chessArray) {
            //这次遍历的为数据
            for (int data : rows) {
                System.out.printf("%d\t",data);
            }
            System.out.println();
        }
    }

    /**
     * 将稀疏数组存入到excel表中
     */
    public static void sparseToExcel(int[][] sparseArray) throws IOException {
        //1.创建一个workbook对应的excel文件
        HSSFWorkbook workbook = new HSSFWorkbook();
        //2.在workbook中创建一个sheet对应excel中的sheet
        Sheet sheet = workbook.createSheet("稀疏数组表");
        //3.在sheet中添加表头
        Row row = sheet.createRow(0);
        //4.创建单元格，设置表头内容
        Cell cell = row.createCell(0);
        cell.setCellValue("行数");
        cell = row.createCell(1);
        cell.setCellValue("列数");
        cell = row.createCell(2);
        cell.setCellValue("数值");
        //5.写入数据
        for (int i = 0; i < sparseArray.length; i++) {
            row = sheet.createRow(i + 1);
            cell = row.createCell(0);
            cell.setCellValue(sparseArray[i][0]);
            cell = row.createCell(1);
            cell.setCellValue(sparseArray[i][1]);
            cell = row.createCell(2);
            cell.setCellValue(sparseArray[i][2]);
        }
        //6.将文件保存到指定的位置
        try {
            //文件放在项目下面的 poi夹下面
            String pathString = "poi";
            File file = new File(pathString);
            //如果文件夹不存在，就创建文件夹
            if (!file.exists()){
                System.out.println("系统指定的路径不存在");
                //创建文件夹
                file.mkdirs();
            }
            String savePath = pathString +"//"+ "sparseArray.xlsx";
            FileOutputStream fos = new FileOutputStream(savePath);
            workbook.write(fos);
            System.err.println("写入成功！！！");
            fos.flush();
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            workbook.close();
        }
    }

    public static void excelToSparseArray() throws IOException {
        //1.创建输入流，读取excel
        File file;
        InputStream is = new FileInputStream("poi//sparseArray.xlsx");
        //2.解析excel
        POIFSFileSystem poiFS = new POIFSFileSystem(is);
        //3.获取workbook
        HSSFWorkbook workbook = new HSSFWorkbook(poiFS);
        //4.获取第一个表单
        HSSFSheet sheet = workbook.getSheetAt(0);
        //5.获取第二行
        HSSFRow row = sheet.getRow(1);
        HSSFCell cell = row.getCell(2);
        //得到稀疏数组的行数
        int sum = (int) cell.getNumericCellValue();
        //创建稀疏数组
        int[][] sparseArray = new int[sum + 1][3];
        //为稀疏数组赋值
        //1.获取excel表最后一行的下标
        int rowNum = sheet.getLastRowNum();
        //从下标1开始读取数据
        for (int i = 1; i <= rowNum; i++) {
            row = sheet.getRow(i);
            sparseArray[i - 1][0] = (int) row.getCell(0).getNumericCellValue();
            sparseArray[i - 1][1] = (int) row.getCell(1).getNumericCellValue();
            sparseArray[i - 1][2] = (int) row.getCell(2).getNumericCellValue();
        }

        //打印从excel表中获取的稀疏数组
        System.err.println("打印从excel表中获取的稀疏数组:");
        for (int[] rows : sparseArray) {
            for (int data : rows) {
                System.out.printf("%d\t",data);
            }
            System.out.println();
        }
    }
}
